package com.leiyuee.gulimall.search.thread;

import java.util.concurrent.*;

public class ThreadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // System.out.println("main......start.....");
        // Thread thread = new Thread01();
        // thread.start();
        // System.out.println("main......end.....");

//         Runable01 runable01 = new Runable01();
//         new Thread(runable01).start();
//
//         FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
//         new Thread(futureTask).start();
//         System.out.println(futureTask.get());

        // service.execute(new Runable01());
        // Future<Integer> submit = service.submit(new Callable01());
        // submit.get();

        System.out.println("main......start.....");
        // CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        //     System.out.println("当前线程：" + Thread.currentThread().getId());
        //     int i = 10 / 2;
        //     System.out.println("运行结果：" + i);
        // }, executor);

        /**
         * 方法完成后的处理
         */
        // CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
        //     System.out.println("当前线程：" + Thread.currentThread().getId());
        //     int i = 10 / 0;
        //     System.out.println("运行结果：" + i);
        //     return i;
        // }, executor).whenComplete((res,exception) -> {
        //     //虽然能得到异常信息，但是没法修改返回数据
        //     System.out.println("异步任务成功完成了...结果是：" + res + "异常是：" + exception);
        // }).exceptionally(throwable -> {
        //     //可以感知异常，同时返回默认值
        //     return 10;
        // });

        /**
         * 方法执行完后端处理
         */
        // CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
        //     System.out.println("当前线程：" + Thread.currentThread().getId());
        //     int i = 10 / 2;
        //     System.out.println("运行结果：" + i);
        //     return i;
        // }, executor).handle((result,thr) -> {
        //     if (result != null) {
        //         return result * 2;
        //     }
        //     if (thr != null) {
        //         System.out.println("异步任务成功完成了...结果是：" + result + "异常是：" + thr);
        //         return 0;
        //     }
        //     return 0;
        // });

        /**
         * 线程串行化：异步编排
         * 1、thenRunL：不能获取上一步的执行结果
         * 2、thenAcceptAsync：能接受上一步结果，但是无返回值
         * 3、thenApplyAsync：能接受上一步结果，有返回值
         *
         */
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动了..." + res);
            return "Hello" + res;
        }, executor);
        System.out.println("main......end....." + future.get());


        /**
         *多任务
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束：" + i);
            return i;
        }, executor);
        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程：" + Thread.currentThread().getId());
            System.out.println("任务2结束：");
            return "Hello";
        }, executor);
        //两个完成
        future01.runAfterBothAsync(future02, () -> {
            System.out.println("任务3：");
        }, executor);
        future01.thenAcceptBothAsync(future02, (f1, f2) -> {
            System.out.println("任务4结束：" + f1 + "-->" + f2);
        }, executor);
        CompletableFuture<String> f3 = future01.thenCombineAsync(future02, (f1, f2) -> {
            return f1 + ":" + f2;
        }, executor);
        f3.get();
        //完成一个
        //不感知
        future01.runAfterEitherAsync(future02, () -> {
            System.out.println("任务5：");
        }, executor);
        //需要相同类型：感知不返回
        future01.acceptEitherAsync(future02, (res) -> {
            System.out.println("任务6：" + res);
        }, executor);
        CompletableFuture<Void> f = future01.acceptEitherAsync(future02, res -> {
            System.out.println("任务7：" + res);
        }, executor);
        f.get();
        //多任务
        CompletableFuture<Object> future00 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务0线程：" + Thread.currentThread().getId());
            System.out.println("任务0结束：");
            return "Hello";
        }, executor);

        CompletableFuture<Void> all = CompletableFuture.allOf(future00, future01, future02, f);
        all.get();//等待所有完成

        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future00, future01, future02, f);
    }

    /**
     * corePoolSize:核心线程数【一直存在】。
     * maximumPoolSize：允许的最大线程数：控制资源并发
     * keepAliveTime： 存活时间。当前线程数量大于核心数量，释放空闲的线程
     * unit：时间单位
     * BlockingQueue：阻塞队列，如果任务有很多，将目前多的任务放在队列里。只要有线程空闲就回去队列取出新的任务执行
     * ThreadFactory：线程创建工厂
     * handler：队列满了后，按照指定的拒绝策略拒绝执行任务
     * <p>
     * 1）线程池创建后准备好core数量的核心线程，准备接收任务
     * 2） core满了，再进来的任务会放入阻塞队列里面，空闲的core会从阻塞队列中获取任务执行
     * 3）阻塞队列满了。开新线程执行，最大只能到max指定的数量
     * 4）max满了就用拒绝策略
     * 4）max执行完成后，有很多空闲。在指定的存活时间后释放max-core
     * <p>
     * 新立即执行 core,然后进入队列，然后开max执行，其余开拒绝策略：抛弃或者同步执行 CallerRunsPolicy
     * <p>
     * 为什么使用线程池
     * 1）降低资源的消耗：通过重复利用已经创建好的线程降低线程的创建和销毁带来的资源的损耗，
     * 2）提高响应速度：当任务来时不需要创建线程就就能执行（切换线程和恢复线程是非常耗费资源的）
     * 3）提高线程的可管理性：使用线程池统一管理，对池内的线程进行统一的管理
     */
    private static void threadPool() {
        ExecutorService threadPool = new ThreadPoolExecutor(
                5,
                200,
                10L,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(10000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        //定时任务的线程池
        ExecutorService service = Executors.newScheduledThreadPool(2);
    }


    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }


    public static class Runable01 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }


    public static class Callable01 implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }
    }


}
